#include "YetiEnemy.h"
#include "YetiNormal.h"
#include "YetiAttack.h"
#include "EntityManager.h"
#include "YetiDistanceDecision.h"
#include "RandomDecision.h"
#include "YetiAttackDecision.h"
#include "YetiNormalDecision.h"
#include "YetiFleeState.h"
#include "YetiFleeDecision.h"
#include "YetiSeekState.h"
#include "YetiSeekDecision.h"
#include "YetiHitState.h"
#include "YetiHitDecision.h"

YetiEnemy::YetiEnemy(AnimationPlayer* yetiAnims, D3DXVECTOR3 position, Level* level)
	: Entity(2000, position, 0, "Enemy"),
	yetiAnims(yetiAnims),
	stateMachine(this),
	particle(position, D3DXVECTOR3(0, 0, 0), 1000.0f),
	gravity(D3DXVECTOR3(0, 500.0f, 0)),
	drag(0.1f, 0.5f),
	level(level)
{
	ForceRegistry::add(&particle, &gravity);
	ForceRegistry::add(&particle, &drag);
	texture = yetiAnims->getCurrentAnimation()->getTexture();
	elapsedTime = 0.0f;
	health = 500;
	
	// Initialise state machine
	player = EntityManager::getNamedEntities("Player")->front();
	stateMachine.addState("YetiNormal", new YetiNormal());
	stateMachine.addState("YetiHitState", new YetiHitState());
	stateMachine.addState("YetiAttack", new YetiAttack(this, player,1.0f)); 
	stateMachine.addState("Seek", new YetiSeekState(this, player, 1.0f));
	stateMachine.addState("Flee", new YetiFleeState(this, player, 1.0f));
	stateMachine.changeState("YetiNormal");
	// Initialise distance decision.
	decisionTree = new YetiDistanceDecision(
									200.0f,
									new YetiDistanceDecision(
										150.0f,
										new YetiAttackDecision(),
										new RandomDecision<YetiEnemy>(
											new YetiAttackDecision(),
    										new YetiFleeDecision())),
									new YetiSeekDecision());
}

void YetiEnemy::update(float frameTime)
{
	if (health <= 0)
	{
		yetiAnims->playAnimation("Die");
		alive = false;
	}

	if (alive)
	{
		particle.update(frameTime);
		position = particle.position;
		yetiAnims->update(frameTime);
		elapsedTime += frameTime;

		if(elapsedTime > 0.5f)
		{
			stateMachine.update(frameTime);
			decisionTree->makeDecision(this);
			elapsedTime = 0.0f;
		}

		// Check collision with player
		D3DSURFACE_DESC yetiDesc;
		texture->GetLevelDesc(0, &yetiDesc);
		D3DXVECTOR3 yetiSize((float)yetiDesc.Width, (float)yetiDesc.Height, 0);
		BoundingBox yetiBox = { position, yetiSize };
		if (player->isAlive())
		{
			D3DSURFACE_DESC playerDesc;
			player->getTexture()->GetLevelDesc(0, &playerDesc);
			D3DXVECTOR3 playerSize((float)playerDesc.Width, (float)playerDesc.Height, 0);
			BoundingBox playerBox = { player->getPosition(), playerSize };
			if (TestCollision(yetiBox, playerBox))
			{
				Message message(player, "Hit", 0);
				MessageHandler::sendMessage(message);
			}
		}
	
		particle.update(frameTime);

		D3DXVECTOR3 movement = particle.position - position;
		D3DXVECTOR3 size((float)yetiDesc.Width, (float)yetiDesc.Height, 0);
		BoundingBox bounds = { position, size };
		position = level->checkCollision(this, bounds, movement);

		if (D3DXVec3Length(&(position - particle.position)) > 0.1f)
		{
			D3DXVECTOR3 contactNormal = position - particle.position;
			D3DXVec3Normalize(&contactNormal, &contactNormal);
			Particle contactParticle(particle.position, D3DXVECTOR3(0, 0, 0), 1000.0f);
			Particle* particles[2] = { &particle, &contactParticle };
			Contact contact(particles, 1.0f, contactNormal);
			contact.resolve(frameTime);
		}
		particle.position = position;
	}
}

void YetiEnemy::draw(ID3DXSprite* sprite)
{
	//First we work out the centre of the frame
	D3DXVECTOR2 centre;
	centre.x = (float)(yetiAnims->getCurrentAnimation()->getFrameWidth() / 2);
	centre.y = (float)(yetiAnims->getCurrentAnimation()->getFrameHeight() / 2);

	/* Now we create a transformation matrix. If flipped, we scale X by -1
	 * we also use the position vector in our transaction */
	D3DXVECTOR3 tempPos = position - level->getOffset();
	 //worldPosition = position - level->getOffset();
	

	D3DXMATRIX mat;
	if(flip)
		D3DXMatrixTransformation2D(&mat, &centre, 0,
								   &D3DXVECTOR2(-1, 1), 0, 0,
								   &D3DXVECTOR2(tempPos.x, tempPos.y));
	else 
		D3DXMatrixTransformation2D(&mat, 0, 0, 0, 0, 0,
								   &D3DXVECTOR2(tempPos.x, tempPos.y));

	//Now we use this transformation to draw with, we set the draw position to 0 to avoid issues
	if (alive)
		yetiAnims->draw(sprite, D3DXVECTOR3(0, 0, 0), mat);
}

void YetiEnemy::handleMessage(Message message)
{
	
	// Handle message code goes here....
	if (message.message == "Die")
	{
		health -= 1;
		stateMachine.changeState("YetiHitState");
	}
}